﻿using System;
using System.Collections.Generic;
using JSH.ITDiplom.OOPC01.PersonalIdentityNumber.BusinessLayer;
using JSH.ITDiplom.OOPC01.PersonalIdentityNumber.BusinessLayer.se;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace JSH.ITDiplom.OOPC01.PersonalIdentityNumber.UnitTest
{
    /// <summary>
    /// Test class SwedishPersonalIdentityNumber
    /// </summary>
    [TestClass]
    public class TestSwedish
    {
        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext { get; set; }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        /// <summary>
        /// Test a number with date 31 feb. 2009
        /// </summary>
        [TestMethod]
        public void Test20090231()
        {
            var swedish = new SwedishPersonalIdentityNumber("310209-4203");

            IList<string> errors;
            bool ok = swedish.Validate(out errors);
            if (ok)
            {
                Assert.Fail("Should fail");
            }
            else
            {
                Util.LogErrors(errors);
                Assert.AreEqual(2, errors.Count, "Two errors expected");
                Assert.AreEqual(
                    "JSH.ITDiplom.OOPC01.PersonalIdentityNumber.BusinessLayer.DateValidation", 
                    errors[0], "Wrong error");
                Assert.AreEqual(
                    "JSH.ITDiplom.OOPC01.PersonalIdentityNumber.BusinessLayer.se.ChecksumValidation",
                    errors[1], "Wrong error");
            }
        }

        /// <summary>
        /// Test generate with birthday 1/1-2001 and Male.
        /// </summary>
        [TestMethod]
        public void TestGenerate20010101Male()
        {
            DateTime birthday = new DateTime(2001, 1, 1);
            const Gender sex = Gender.Female;
            IList<string> personalNumbers =
                SwedishPersonalIdentityNumber.Generate(birthday,
                sex);
            Console.WriteLine("Number of personal numbers=" + personalNumbers.Count);
            int i = 0;
            foreach (string s in personalNumbers)
            {
                i++;
                Console.WriteLine("" + i + " - " + s);
                var swedish = new SwedishPersonalIdentityNumber(s);
                Assert.IsTrue(swedish.Validate(), "Error");
                Assert.AreEqual(birthday, swedish.BirthDay, "Wrong birthday");
                Assert.AreEqual(sex, swedish.Gender, "Wrong gender");
            }
        }

        /// <summary>
        /// Test generate with birthday 1/1-2001 and Female.
        /// </summary>
        [TestMethod]
        public void TestGenerate20010101Female()
        {
            DateTime birthday = new DateTime(2001, 1, 1);
            const Gender sex = Gender.Female;
            IList<string> personalNumbers = 
                SwedishPersonalIdentityNumber.Generate(birthday,
                sex);
            Console.WriteLine("Number of personal numbers=" + personalNumbers.Count);
            int i = 0;
            foreach (string s in personalNumbers)
            {
                i++;
                Console.WriteLine("" + i + " - " + s);
                var swedish = new SwedishPersonalIdentityNumber(s);
                Assert.IsTrue(swedish.Validate(), "Error");
                Assert.AreEqual(birthday, swedish.BirthDay, "Wrong birthday");
                Assert.AreEqual(sex, swedish.Gender, "Wrong gender");
            }
        }

        /// <summary>
        /// Test generate with birthdat 1/1-1905 (> 100 years) and female.
        /// </summary>
        [TestMethod]
        public void TestGenerate19050101Female()
        {
            DateTime birthday = new DateTime(1905, 1, 1);
            const Gender sex = Gender.Female;
            IList<string> personalNumbers =
                SwedishPersonalIdentityNumber.Generate(birthday,
                sex);
            Console.WriteLine("Number of personal numbers=" + personalNumbers.Count);
            int i = 0;
            foreach (string s in personalNumbers)
            {
                i++;
                Console.WriteLine("" + i + " - " + s);
                var swedish = new SwedishPersonalIdentityNumber(s);
                Assert.IsTrue(swedish.Validate(), "Error");
                Assert.AreEqual(birthday, swedish.BirthDay, "Wrong birthday");
                Assert.AreEqual(sex, swedish.Gender, "Wrong gender");
            }
        }

        /// <summary>
        /// Test "Age over 199" exception.
        /// </summary>
        [TestMethod]
        public void TestGenerateException()
        {
            try
            {
                SwedishPersonalIdentityNumber.Generate(new DateTime(1700, 1, 1),
                    Gender.Female);
                Assert.Fail("Should throw an exception");
            }
            catch (ArgumentException ae)
            {
                Assert.AreEqual("Age over 199", ae.Message, "Wrong exception message");
            }
        }
    }
}